package com.houger.service;

import cn.hutool.core.date.DateTime;
import com.houger.dto.RedPacket;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author Houger.
 * @date 2024年04月09日 15:43.
 */
@Service
@Slf4j
public class RedPacketService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    public String sendRedPacket(RedPacket redPacket) {
        redPacket.setRedPacketId(UUID.randomUUID().toString().replace("-",""));
        String script =
            """
                    redis.call('hset', KEYS[1], "total_amount", ARGV[1])
                    redis.call('hset', KEYS[1], "total_count", ARGV[2])
                    redis.call('hset', KEYS[1], "send_time", ARGV[3])
                    redis.call('expire', KEYS[1], 3600*24)
                    return "ok"
                """;

        RedisScript<String> redisScript = new DefaultRedisScript<>(script, String.class);
        List<String> keys = List.of("rp:send:hash:" + "{" + redPacket.getRedPacketId() + "}");
        final String res = stringRedisTemplate.execute(redisScript, keys, redPacket.getTotalAmount(), redPacket.getTotalNum(), DateTime.now().toString());
        log.info("res="+ res);
        if ("ok".equals(res)){
            return redPacket.getRedPacketId();
        }
        return "fail";
    }

    public String grabRedPacket(String redPacketId, String userId) {
        String script =
            """   
                    -- 是否已抢
                    local exists = redis.call('HEXISTS', KEYS[2], ARGV[1])
                    if exists == 1 then
                       return '1'
                    end
                    -- 是否还有红包
                    local totalCount = tonumber(redis.call("hget", KEYS[1], 'total_count'))
                    if totalCount <= 0 then
                       return '-1'
                    end
                    
                    local totalAmount = tonumber(redis.call("hget", KEYS[1], 'total_amount'))
                    math.randomseed(tostring(redis.call('TIME')[1] * 1000000 + redis.call('TIME')[2]))
                    if totalCount == 1 then
                        local money = string.format("%.2f",totalAmount)
                        local luaString = '{"money": "%s", "time": "%s"}'
                        local newStr = string.format(luaString, money,"2024-04-17 17:32:48")
                        redis.call("hset", KEYS[2], ARGV[1], newStr)
                        redis.call("hset", KEYS[1], 'total_amount',0)
                        redis.call("hset", KEYS[1], 'total_count', 0)
                        return money
                    end
                    local average = totalAmount / totalCount
                    local maxMoney = average * 2
                    local money = math.random() * maxMoney
                    money = math.max(money, 0.01)
                    local min = totalAmount - totalCount + 1
                    money = math.min(money, min)
                    totalAmount=totalAmount-money
                    money = string.format("%.2f",money)
                    local luaString = '{"money": "%s", "time": "%s"}'
                    local newStr = string.format(luaString, money,"2024-04-17 17:32:48")
                    redis.call("hset", KEYS[2], ARGV[1], newStr)
                    redis.call("hset", KEYS[1], 'total_amount',string.format("%.2f",totalAmount))
                    redis.call("hset", KEYS[1], 'total_count', totalCount-1)
                    redis.call('expire', KEYS[2], 3600*48)
                    return money
                """;
        RedisScript<String> redisScript = new DefaultRedisScript<>(script, String.class);
        List<String> keys = List.of("rp:send:hash:" + "{" + redPacketId + "}","rp:grab:hash:" + "{" + redPacketId + "}");
        final String money = stringRedisTemplate.execute(redisScript, keys, userId);
        log.info(money);
        if ("1".equals(money)) return "红包已领取";
        if ("-1".equals(money)) return "红包已抢光";
        return "抢到了"+money+"元";
    }

    public Map<Object,Object> grabRedPacketList(String redPacketId){
        final Map<Object, Object> grabRedPacketMap = stringRedisTemplate.opsForHash().entries("rp:grab:hash:" + "{" + redPacketId + "}");
        final String startTime = stringRedisTemplate.opsForValue().get("rp:send:time:" + "{" + redPacketId + "}");
        return grabRedPacketMap;


    }
}

